package generateCode;

import com.cloud.core.db.entity.DBEntity;
import com.cloud.core.db.mapper.MyDBMapper;
import com.github.pfmiles.minvelocity.TemplateUtil;
import com.github.pfmiles.org.apache.velocity.Template;
import com.github.pfmiles.org.apache.velocity.VelocityContext;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import vip.BaseTest;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by cloudy.xie on 17/12/13.
 */
public class MybatisGenerator extends BaseTest {
    private Logger logger = Logger.getLogger(MybatisGenerator.class);

    private final String dataBaseName = "cloudspider";
    private final String prePackageName = "com.cloud.core.db";
    private final String mapperPackageName = prePackageName+".mapper";
    private final String entityPackageName = prePackageName+".entity";

    @Autowired
    private MyDBMapper myDBMapper;

    private static VelocityContext context = new VelocityContext();

    @Test
    public void generator(){
        logger.info("+++++++++++++++++++++++++");
        logger.info("+++++++++++++++++++++++++");
        logger.info(" 开始对数据库所有表生产对应的mybatis文件");

        List<String>  allTables = myDBMapper.getAllTable(dataBaseName) ;
        if(allTables == null || allTables.isEmpty()){
            logger.info("database="+dataBaseName+",无数据表,请先配置");
            logger.info("+++++++++++++++++++++++++");
            return;
        }
        for(String tableName:allTables){
            generatorSingleTable(tableName);
            logger.info("tableName="+tableName+",生产成功");
        }
        logger.info("+++++++++++++++++++++++++");
        logger.info("+++++++++++++++++++++++++");
    }

    private void generatorSingleTable(String tableName){
        List<DBEntity> feildInfos= myDBMapper.getAllColumns(dataBaseName,tableName);
        feildInfos = feildInfos.stream().filter(p-> !"id".equalsIgnoreCase(p.getColumn_name()))
                .map(p->dbTypeToJava(p)).collect(Collectors.toList());

        generatorFile(tableName, entityPackageName, feildInfos, "Entity.vm");
        generatorFile(tableName, mapperPackageName, feildInfos, "Mapper.vm");
    }

    private void generatorFile(String tableName,String packageName,List<DBEntity> feildInfos,String temp){
        String className = underlineToCamel(tableName.replace("t",""));
        boolean timestampFlag = false;
        boolean dateFlag = false;
        for (DBEntity dbEntity:feildInfos){
            if("Date".equals(dbEntity.getDataType())){
                dateFlag = true;
            }
            if("Timestamp".equals(dbEntity.getDataType())){
                timestampFlag = true;
            }
        }

        context.put("prePackageName", prePackageName);
        context.put("packageName", packageName);
        context.put("className", className);
        context.put("feildInfos", feildInfos);
        context.put("tableName",tableName);
        context.put("timestampFlag",timestampFlag);
        context.put("dateFlag",dateFlag);
        context.put("key","#{id}");

        Template template = TemplateUtil.getTemplate(temp);
        StringWriter writer = new StringWriter();
        template.merge(context, writer);

        String packagePath = packageName.replace(".", "/");
        File file = new File(System.getProperty("user.dir") + "/src/main/java/" + packagePath,
                className+temp.replace("vm","java"));
        try {
            FileUtils.writeStringToFile(file, writer.toString(), "utf-8");
        } catch (IOException e) {
            logger.error("",e);
        }
    }

    private DBEntity dbTypeToJava(DBEntity entity){
        switch (entity.getData_type().toLowerCase()){
            case "integer" :entity.setDataType("Long");break;
            case "bigint" :entity.setDataType("Long");break;
            case "int" :entity.setDataType("Integer");break;
            case "tinyint" :entity.setDataType("Integer");break;
            case "smallint" :entity.setDataType("Integer");break;
            case "mediumint" :entity.setDataType("Integer");break;
            case "varchar" :entity.setDataType("String");break;
            case "char" :entity.setDataType("String");break;
            case "text" :entity.setDataType("String");break;
//            case "blob" :entity.setDataType("byte[]");break;
            case "bit" :entity.setDataType("Boolean");break;
            case "boolean" :entity.setDataType("Boolean");break;
            case "float" :entity.setDataType("Float");break;
            case "double" :entity.setDataType("Double");break;
            case "date" :entity.setDataType("Date");break;
            case "datetime" :entity.setDataType("Timestamp");break;
        }
        return entity;
    }

    private String underlineToCamel(String param){
        if (param==null||"".equals(param.trim())){
            return "";
        }
        int len=param.length();
        StringBuilder sb=new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c=param.charAt(i);
            if(i==0 && c!='_'){
                sb.append(Character.toUpperCase(param.charAt(i)));
            }else if (c=='_'){
                if (++i<len){
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }
}
